package com.henushang.ranking.dao.impl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.henushang.ranking.dao.RankingDataDao;
import com.henushang.ranking.domain.CategoryInfo;
import com.henushang.ranking.domain.RankingData;
import com.henushang.ranking.domain.RankingDataResponseVo;
import com.henushang.ranking.domain.WebsiteInfo;
import com.henushang.ranking.service.CategoryService;
import com.henushang.ranking.service.RankingDataService;
import com.henushang.ranking.service.WebsiteService;
import com.henushang.ranking.util.JSONUtil;

@Service
public class RankingDataServiceImpl implements RankingDataService {

    @Autowired
    @Qualifier("rankingDataLatestDao")
    private RankingDataDao rankingDataLatestDao;

    @Autowired
    private WebsiteService websiteService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    @Qualifier("rankingDataDao")
    private RankingDataDao rankingDataDao;

    @Override
    public Map<WebsiteInfo, List<RankingData>> getRankingDataByCategory(String cateId) {
        Map<String, Object> query = new HashMap<>(1);
        query.put("category_id", cateId);
        List<RankingData> rankingDataList = rankingDataLatestDao.getListByQueryMap(query);
        Map<String, WebsiteInfo> allSiteInfoMap = getAllSiteInfoMap();

        Map<WebsiteInfo, List<RankingData>> result = new HashMap<>(rankingDataList.size());
        rankingDataList.stream().forEach(rank -> {
            addToMap(result, allSiteInfoMap.get(rank.getSite_id()), rank);
        });
        return result;
    }

    private static void addToMap(Map<WebsiteInfo, List<RankingData>> map, WebsiteInfo websiteInfo,
            RankingData rankingData) {
        if (map == null) {
            map = new HashMap<>();
        }
        if (map.containsKey(websiteInfo)) {
            map.get(websiteInfo).add(rankingData);
        } else {
            List<RankingData> list = new ArrayList<>();
            list.add(rankingData);
            map.put(websiteInfo, list);
        }
    }

    @Override
    public Map<CategoryInfo, Map<WebsiteInfo, List<RankingData>>> getRankingDataByCategory() {
        List<RankingData> rankingDataList = rankingDataLatestDao.getListByQueryMap(new HashMap<>());
        Map<String, CategoryInfo> allCateinfoMap = getAllCateInfoMap();
        Map<String, WebsiteInfo> allSiteInfoMap = getAllSiteInfoMap();

        Map<CategoryInfo, Map<WebsiteInfo, List<RankingData>>> map = new TreeMap<CategoryInfo, Map<WebsiteInfo, List<RankingData>>>(
                new Comparator<CategoryInfo>() {

                    @Override
                    public int compare(CategoryInfo o1, CategoryInfo o2) {
                        if (o1.getWeight() > o2.getWeight()) {
                            return -1;
                        } else if (o1.getWeight() < o2.getWeight()) {
                            return 1;
                        }
                        return 0;
                    }
                });
        rankingDataList.forEach(rankingData -> {
            WebsiteInfo websiteInfo = allSiteInfoMap.get(rankingData.getSite_id());
            CategoryInfo categoryInfo = allCateinfoMap.get(rankingData.getCategory_id());
            if (categoryInfo != null && websiteInfo != null) {
                addToMap(map, categoryInfo, websiteInfo, rankingData);
            }
        });

        System.out.println(map.size());

        return map;
    }


    @Override
    public Map<WebsiteInfo, Map<CategoryInfo, List<RankingData>>> getIndexRankingData() {
        List<RankingData> rankingDataList = rankingDataLatestDao.getListByQueryMap(new HashMap<>());
        List<RankingDataResponseVo> resultList = new ArrayList<>(rankingDataList.size());

        Map<String, CategoryInfo> allCateinfoMap = getAllCateInfoMap();
        Map<String, WebsiteInfo> allSiteInfoMap = getAllSiteInfoMap();

        Map<WebsiteInfo, List<RankingDataResponseVo>> map = new HashMap<>();
        rankingDataList.forEach(rankingData -> {
            RankingDataResponseVo responseVo = new RankingDataResponseVo();
            responseVo.setRankingData(rankingData);
            WebsiteInfo websiteInfo = allSiteInfoMap.get(rankingData.getSite_id());
            responseVo.setWebsiteInfo(websiteInfo);
            CategoryInfo categoryInfo = allCateinfoMap.get(rankingData.getCategory_id());
            responseVo.setCategoryInfo(categoryInfo);
            addToMap(map, websiteInfo, responseVo);
        });

        System.out.println(resultList);
        return null;
    }

    @Override
    public RankingData getRankingDataById(String id) {
        return rankingDataDao.getOne(id);
    }

    private void addToMap(Map<CategoryInfo, Map<WebsiteInfo, List<RankingData>>> map,
            CategoryInfo categoryInfo, WebsiteInfo websiteInfo, RankingData rankingData) {
        if (map == null) {
            map = new HashMap<>();
        }
        if (map.containsKey(categoryInfo)) {
            Map<WebsiteInfo, List<RankingData>> webMap = map.get(categoryInfo);
            if (webMap.containsKey(websiteInfo)) {
                webMap.get(websiteInfo).add(rankingData);
            } else {
                List<RankingData> list = new ArrayList<>();
                list.add(rankingData);
                webMap.put(websiteInfo, list);
            }
        } else {
            Map<WebsiteInfo, List<RankingData>> webMap = new HashMap<>();
            List<RankingData> rankingList = new ArrayList<>();
            rankingList.add(rankingData);
            webMap.put(websiteInfo, rankingList);
            map.put(categoryInfo, webMap);
        }
    }

    private void addToMap(Map<WebsiteInfo, List<RankingDataResponseVo>> map,
            WebsiteInfo websiteInfo, RankingDataResponseVo responseVo) {
        if (map.containsKey(websiteInfo)) {
            map.get(websiteInfo).add(responseVo);
        } else {
            List<RankingDataResponseVo> list = new ArrayList<>();
            list.add(responseVo);
            map.put(websiteInfo, list);
        }

    }

    private Map<String, CategoryInfo> getAllCateInfoMap() {
        List<CategoryInfo> list = categoryService.getCategoryList(new HashMap<>());
        Map<String, CategoryInfo> map = new HashMap<>(list.size());
        list.forEach(categoryInfo -> map.put(categoryInfo.get_id(), categoryInfo));
        return map;
    }

    private Map<String, WebsiteInfo> getAllSiteInfoMap() {
        List<WebsiteInfo> list = websiteService.getWebsiteList(new HashMap<>());
        Map<String, WebsiteInfo> map = new HashMap<>(list.size());
        list.forEach(websiteInfo -> map.put(websiteInfo.get_id(), websiteInfo));
        return map;
    }

    public static void main(String[] args) {
        RankingDataService service = new RankingDataServiceImpl();
        JSONUtil.toJson(service.getIndexRankingData());
    }
}
